#pragma once
#include <iostream>
#include <sys/epoll.h>

#include "Common.hpp"
#include "Log.hpp"

using namespace LogModule;

class Epoller{
public:
    Epoller()
    :_epfd(-1)
    {
        _epfd = epoll_create(128);
        if(_epfd < 0)
        {
            LOG(LogLevel::ERROR) << "epoll_create error";
        }
        LOG(LogLevel::FATAL) << "epoll_create success";
    }
    int EventHelper(int sockfd, uint32_t events, int oper)
    {
        struct epoll_event event;
        event.data.fd = sockfd;//这里用文件描述符,方便后序有链接到来,我们根据文件描述符查找连接对象,做相应的处理
        event.events = events;
        int n = epoll_ctl(_epfd, oper, sockfd, &event);
        return n;
    }
    //添加
    void EpllAddEvent(int fd, int event)
    {
        int n = EventHelper(fd, event, EPOLL_CTL_ADD);
        if(n < 0)
        {
            LOG(LogLevel::ERROR) << "epoll_ctl_add error";
        }
        LOG(LogLevel::FATAL) << "epoll_ctl_add success: " << fd;
    }

    //删除
    void EpollDelEvent(int fd)
    {
        int n = epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, nullptr);
        if(n < 0)
        {
            LOG(LogLevel::ERROR) << "epoll_ctl_del error";
        }
        LOG(LogLevel::FATAL) << "epoll_ctl_del success: " << fd;
    }
    //修改
    void EpollModEvent(int fd, int event)
    {
        int n = EventHelper(fd, event, EPOLL_CTL_MOD);
        if(n < 0)
        {
            LOG(LogLevel::ERROR) << "epoll_ctl_mod error";
        }
        LOG(LogLevel::FATAL) << "epoll_ctl_mod success: " << fd;
    }
    //等待就绪事件
    int WaitEvents(struct epoll_event revs[], int num)
    {
        int n = epoll_wait(_epfd, revs, num, -1);
        if(n < 0)
        {
            LOG(LogLevel::ERROR) << "epoll_wait error";
        }
        else if(n == 0)
        {
            LOG(LogLevel::ERROR) << "epoll_wait timeout...";
        }
        else 
        {
            LOG(LogLevel::FATAL) << "epoll_wait success";
        }
        //不要忘记返回值
        return n;
    }
    ~Epoller()
    {
        if(_epfd > 0)
        {
            close(_epfd);
        }
    }
private:
    int _epfd;
};